//
// Created by LiuYou on 2021/5/23.
//


#include <unordered_map>
#include <vector>
#include <deque>
#include <iostream>

static bool
BreadthFirstSearch(std::__umap_hashtable<std::string, std::vector<const char*>>& graph);

/**
 * @brief BreadthFirstSearch02.cpp这个文件已经成功实现了BFS算法。
 *
 * @return 0
 */
int main() {
    std::__umap_hashtable<std::string, std::vector<const char*>> graph;
    graph["you"] = {"alice", "bom", "claire"};
    graph["bom"] = {"anuj", "peggy"};
    graph["alice"] = {"peggy"};
    graph["claire"] = {"thom", "jonny"};
    graph["anuj"] = {};
    graph["peggy"] = {};
    graph["thom"] = {};
    graph["jonny"] = {};

//    std::deque<std::vector<const char*>> deque;
//    deque.push_back(graph["you"]);
//    std::cout << deque.size() << std::endl;
//    std::cout << *deque.back().begin() << std::endl;

//    std::deque<const char*> deque;
//    for (const auto& item : graph["you"]) {
//        deque.push_back(item);
//    }
//    for (const auto& item : deque) {
//        std::cout << item << std::endl;
//    }

    BreadthFirstSearch(graph);



    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    // begin
    // {

/*    // todo 注意: 这些都是可以的！！！！！！！！！！！！！！！
    //  这要涉及到std::string就不行！！！！
    for (const auto& item : graph["claire"]) {
        std::cout << item << std::endl;
    }
    const char* str = "claire";
    for (const auto& item : graph[str]) {
        std::cout << item << std::endl;
    }


    {
        // TODO 注意: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //  这里哈希表对象使用下标运算符, 不要使用标准库string对象直接返回C风格的字符串, 因为会不执行代码！！！！
        //  非常重要, 也非常玄学！
        std::string string(str);
        for (const auto& item : graph[string.data()]) {
            std::cout << item << std::endl;
        }
        std::string s(str);
//        const char* data = s.data();
        // 强转也不行！！！！！！！！！！！！！！！！
        const char* data = static_cast<const char*>(s.data());
        std::cout << "data: " << data << std::endl;
//    const char* data = s.c_str();
        for (const auto& item : graph[data]) {
            std::cout << item << std::endl;
        }
    }*/

    // }
    // end
    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    std::exit(0);
}

static bool
BreadthFirstSearch(std::__umap_hashtable<std::string, std::vector<const char*>>& graph) {
    std::deque<const char*> deque;
    for (const auto& item : graph["you"]) {
        deque.push_back(item);
    }
//    std::vector<std::string> searched{"你好"};
    std::vector<std::string> searched;
    bool flag = false;
    while (!deque.empty()) {
//        const char* person = *deque.cbegin();
        std::string person(deque.front());
        deque.pop_front();
        for (const auto& item : searched) {
            if (item == person) {
                flag = true;
            }
        }
        if (flag) {
            // TODO 注意: 通过调试这里需要加上一句。
            flag = false;
        } else {
            if (person[person.size() - 1] == 'm') {
                std::cout << person << " 是一个芒果销售商" << std::endl;
                // TODO 注意: 这里这个退出如果注释掉就是打印所有是芒果销售商, 如果加上这句就是距离最近的芒果销售商。
//                return true;
            } else {
//                const char* string = person.data();
//                for (const auto& item : graph[string]) {

                // TODO 注意: 通过调试得知, 根本不会进入这个循环, 不知道为什么???????
                //  原因是使用std::string对象就是不行。
                //  解决见: BreadthFirstSearch02.cpp。
                for (const auto& item : graph[person]) {
                    deque.push_back(item);
                }

                searched.push_back(person);
            }
        }
    }
    return false;
}


#ifdef Test01

int main() {
    std::__umap_hashtable<const char*, std::vector<const char* >> graph;
    graph["you"] = {"alice", "bob", "claire"};
    graph["bob"] = {"anuj", "peggy"};
    graph["alice"] = {"peggy"};
    graph["claire"] = {"thom", "jonny"};
    graph["anuj"] = {};
    graph["peggy"] = {};
    graph["thom"] = {};
    graph["jonny"] = {};

    std::deque<std::vector<const char*>> deque;
//    deque += graph["you"];
    deque.push_back(graph["you"]);
    std::cout << deque.size() << std::endl;
    std::cout << *deque.back().begin() << std::endl;

//    std::cout << graph["you"] << std::endl;
    for (const auto& item : graph["you"]) {
        std::cout << item << std::endl;
    }

//    for (const auto& item : deque) {
//        std::cout << item. << std::endl;
//    }


//    while (!deque.empty()) {
//        std::vector<const char*>& person = *deque.begin();
//        deque.pop_front();
//        person[person.size() - 1]
//    }

    return 0;
}

#endif